/**
 * 
 */
package de.cbf.cam.dsa.battle.ui.windows.attackWindow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

import de.cbf.cam.dice.entities.RollData;
import de.cbf.cam.dsa.battle.ui.composites.CompositeDiceRoll;
import de.cbf.cam.dsa.battle.ui.windows.attackWindow.AttackController.RollDiceListener;

/**
 * @author Nebelritter
 *
 */
public class SideDices extends Composite {
	public static final int SIDE_ATTACKS 			= 1;
	public static final int SIDE_ATTACKMANEUVERS	= 2;
	public static final int SIDE_DEFENDER			= 3;
	public static final int SIDE_DAMAGE				= 4;
	
	/**
	 * @uml.property  name="compositeAttacks"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Composite compositeAttacks;
	
	/**
	 * @uml.property  name="compositeAttackManeuvers"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Composite compositeAttackManeuvers;
	/**
	 * @uml.property  name="attackerInside"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Composite attackerInside;
	/**
	 * @uml.property  name="compositeDefenderSide"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Composite compositeDefenderSide;
	/**
	 * @uml.property  name="compositeDamageSide"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Composite compositeDamageSide;
	
	/**
	 * @uml.property  name="openChecks"
	 * @uml.associationEnd  multiplicity="(0 -1)" ordering="true" elementType="java.util.List" qualifier="compositeName:java.lang.String de.cbf.cam.dsa.battle.ui.composites.CompositeDice"
	 */
	private HashMap<String, CompositeDiceRoll> openChecks = new HashMap<String, CompositeDiceRoll>();
	
//	private CompositeDiceCheck defenderDiceUI;
//	private CompositeDiceCheck attackerDiceUI;	

	
	

	/**
	 * @param parent
	 * @param style
	 */
	public SideDices(Composite parent, int style) {
		super(parent, style);
		
		GridLayout layout = new GridLayout(1,true);
		layout.marginBottom = 0;
		layout.marginTop	= 0;
		layout.marginLeft   = 0;
		layout.marginRight  = 0;
		layout.marginWidth  = 0;
		layout.marginHeight = 0;						
		
		GridLayout layout2 = new GridLayout(2,true);
		layout.marginBottom = 0;
		layout.marginTop	= 0;
		layout.marginLeft   = 0;
		layout.marginRight  = 0;
		layout.marginWidth  = 0;
		layout.marginHeight = 0;
		setLayout(layout2);			
		
		ScrolledComposite attackerSide = new ScrolledComposite(this, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL);
		attackerSide.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,1,1));
		attackerSide.setLayout(layout);

			attackerInside = new Composite(attackerSide, SWT.NONE);
			attackerInside.setLayoutData(new GridData(GridData.FILL_BOTH));
			attackerSide.setLayout(layout);
		
				compositeAttacks = new Composite(attackerInside,SWT.NONE);//;
				compositeAttacks.setLayoutData(new GridData(GridData.FILL_BOTH));
				compositeAttacks.setLayout(new GridLayout(1,false));
				
				compositeAttackManeuvers = new Composite(attackerInside,SWT.NONE);//;
				compositeAttackManeuvers.setLayoutData(new GridData(GridData.FILL_BOTH));
				compositeAttackManeuvers.setLayout(new GridLayout(1,false));
			attackerInside.pack();	
		attackerSide.setContent(attackerInside);
				
		ScrolledComposite defenderSide = new ScrolledComposite(this, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL);
		defenderSide.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,1,1));
		defenderSide.setLayout(layout);
		
			compositeDefenderSide = new Composite(defenderSide,SWT.NONE);
			compositeDefenderSide.setLayoutData(new GridData(GridData.FILL_BOTH));
			compositeDefenderSide.setLayout(new GridLayout(1,false));
		defenderSide.setContent(compositeDefenderSide);
		
		ScrolledComposite damageSide = new ScrolledComposite(this, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL);
		damageSide.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,2,1));
		damageSide.setLayout(layout);
		
			compositeDamageSide = new Composite(damageSide,SWT.NONE);
			compositeDamageSide.setLayoutData(new GridData(GridData.FILL_BOTH));
			compositeDamageSide.setLayout(new GridLayout(1,false));	
		damageSide.setContent(compositeDamageSide);
		
//		//TODO change part in the middle to accomodate the dice check composites, that are dynamically generated		
//		attackerDiceUI = new CompositeDiceCheck(compositeAttacks, SWT.NONE);
//		attackerDiceUI.setLayoutData(new GridData(SWT.RIGHT,SWT.TOP,false,false,1,1));
//		attackerDiceUI.setTitle("Angreifer");		
//				
//		defenderDiceUI = new CompositeDiceCheck(compositeDefenderSide, SWT.NONE);
//		defenderDiceUI.setLayoutData(new GridData(SWT.LEFT,SWT.BOTTOM,false,false,1,1));
//		defenderDiceUI.setTitle("Verteidiger");		
//		defenderDiceUI.disable();
//		
				
		compositeAttacks.pack();
		compositeAttackManeuvers.pack();
		attackerInside.pack();
		compositeDefenderSide.pack();
		compositeDamageSide.pack();
		
		layout(true,true);		
	}
	
	public List<CompositeDiceRoll> getOpenChecksByName(String name){
		List<CompositeDiceRoll> resultList = new ArrayList<CompositeDiceRoll>();
		Set<String> openCheckNames = openChecks.keySet(); 
		for (Iterator<String> iterator = openCheckNames.iterator(); iterator.hasNext();) {
			String openCheckName = (String) iterator.next();
			if(openCheckName.startsWith(name)){
				resultList.add(openChecks.get(openCheckName));
			}
		}
		return resultList;
	}
		
	public void packAll(){
		compositeAttacks.pack();
		compositeAttackManeuvers.pack();
		attackerInside.pack();
		compositeDefenderSide.pack();
		compositeDamageSide.pack();
		layout(true,true);
	}
/*	
	public CompositeDice addDiceCheck(ThrowDefinition diceThrowDefinition,int side) throws Exception{
		//find place to add
		CompositeDice newComposite;
		switch (side) {
		case SIDE_ATTACKS:{
			newComposite = CompositeDice.getCompositeForThrow(diceThrowDefinition, compositeAttacks);	
			compositeAttacks.pack();
			compositeAttackManeuvers.pack();
			attackerInside.pack();
			break;
		}
		case SIDE_ATTACKMANEUVERS:{
			newComposite = CompositeDice.getCompositeForThrow(diceThrowDefinition, compositeAttackManeuvers);			
			compositeAttackManeuvers.pack();
			attackerInside.pack();
			break;
		}
		case SIDE_DEFENDER:{
			newComposite = CompositeDice.getCompositeForThrow(diceThrowDefinition, compositeDefenderSide);			
			compositeDefenderSide.pack();
			break;
		}
		case SIDE_DAMAGE:{
			newComposite = CompositeDice.getCompositeForThrow(diceThrowDefinition, compositeDamageSide);
			compositeDamageSide.pack();
			break;
		}
		default:
			//if wrong side specified return, because it is not addable
			throw new Exception("Specified side does not exist");
		}
		//add to map
		openChecks.put(diceThrowDefinition.getTitle(),newComposite);
		//listeners
		List<ListenerEntry> listeners = diceThrowDefinition.getListenersOtherComposite();
		for (Iterator<ListenerEntry> iterator = listeners.iterator(); iterator.hasNext();) {
			ListenerEntry listenerEntry = (ListenerEntry) iterator.next();
			//set composite for Listener
			try{				
				listenerEntry.listener.setSideDicesComposite(this);
			}catch (Exception e) {
				Activator.logger.debug("Cannot add Listener: "+listenerEntry.listener.getClass().getSimpleName()+" to Composite: "+newComposite.getTitle()+"\n"+
						"Reason: "+e.getLocalizedMessage());
			}
			//add listener to target composite
			List<CompositeDice> targetCompositeDices = getOpenChecksByName(listenerEntry.compositeDiceName);
			for (Iterator<CompositeDice> compositeIterator = targetCompositeDices.iterator(); compositeIterator.hasNext();) {
				CompositeDice targetCompositeDice = (CompositeDice) compositeIterator.next();
				targetCompositeDice.addEventListener(listenerEntry.listener,listenerEntry.event);
				listenerEntry.listener.initFromComposite(targetCompositeDice);
				Activator.logger.debug("Listener: "+listenerEntry.listener.getClass().getSimpleName()+" added to Composite: "+targetCompositeDice.getTitle());
			}				
		}
		// actualization of composite after adding part		
		layout(true,true);
		newComposite.setFunctional(true);		
		return newComposite;
	}
*/	
	public void removeComposite(String compositeName){
		CompositeDiceRoll compositeDice = openChecks.remove(compositeName);
		if(compositeDice != null){		
			compositeDice.dispose();
			layout(true,true);
		}				
	}
	
	public void clearAllChecks(){
		openChecks.clear();
		clearComposite(compositeAttacks);
		clearComposite(compositeDefenderSide);
		clearComposite(compositeDamageSide);
		layout(true,true);
	}
	
	private void clearComposite(Composite composite){
		Control[] children = composite.getChildren();
		for (int i = 0; i < children.length; i++) {
			if (children[i] instanceof CompositeDiceRoll) {
				CompositeDiceRoll compositeDice = (CompositeDiceRoll) children[i];
				compositeDice.clearListeners();
				compositeDice.dispose();
			}
		}
	}
	public CompositeDiceRoll addThrowData(RollData data, int side, RollDiceListener rollDiceListener) throws Exception {
		Composite paintArea;
		//evaluate side		
		switch (side) {
		case SideDices.SIDE_ATTACKS:{
			paintArea = compositeAttacks;
			break;
		}
		case SideDices.SIDE_ATTACKMANEUVERS:{
			paintArea = compositeAttackManeuvers;
			break;
		}
		case SideDices.SIDE_DEFENDER:{
			paintArea = compositeDefenderSide;
			break;
		}
		case SideDices.SIDE_DAMAGE:{
			paintArea = compositeDamageSide;
			break;
		}
		default:
			throw new Exception("Cannot add Rolldefnition: Side unknown");			
		}
		CompositeDiceRoll compositeTest = CompositeDiceRoll.getCompositeForThrow(data, paintArea);
		openChecks.put(compositeTest.getTitle(),compositeTest);
		compositeTest.setLayoutData(new GridData(GridData.FILL_BOTH));
		//add listener to roll dice
		compositeTest.addEventListener(rollDiceListener, CompositeDiceRoll.EVENT_RollDice);
		//
		paintArea.pack();
		packAll();	
		return compositeTest;
	}

	
	
//	===========================
//		getter
//	===========================	
	
//	===========================
//		setter
//  ===========================
	
//	===========================
//		listener registry
//  ===========================	
	
//	===========================
//		listeners
//  ===========================	
}
